package edu.neu.cs6515.net.test.integration;

import java.util.ArrayList;
import java.util.List;

import com.google.java.contract.ContractAssertionError;

import edu.neu.cs6515.board.HexagonBoard;
import edu.neu.cs6515.net.ProxyOfTurnProxy;
import edu.neu.cs6515.net.test.unit.PredefinedInOutPut;
import edu.neu.cs6515.xml.Bad;
import edu.neu.cs6515.xml.Board;
import edu.neu.cs6515.xml.False;
import edu.neu.cs6515.xml.Placement;
import edu.neu.cs6515.xml.Results;
import edu.neu.cs6515.xml.Tile;
import edu.neu.cs6515.xml.w12.ReRackPlease;
import edu.neu.cs6515.xml.w12.RemoteTurnInput;
import edu.neu.cs6515.xml.w12.RemoteTurnResults;
import edu.neu.cs6515.xml.w12.Rerack;
import edu.neu.cs6515.xml.w12.Rerackable;
import edu.neu.cs6515.xml.w12.TurnTest;
import edu.neu.cs6515.xml.w12.XMLTurn;

public class RemoteTurnProxyTestRunner {

    public RemoteTurnResults runGameAndGetResults(final TurnTest tt) {
        XMLTurn turn = tt.getTurn();
        Board board = tt.getTurn().getBoard();
        HexagonBoard hexBoard = new HexagonBoard(tt.getTurn().getBoard().getPlayers());
        hexBoard.updateHexagonBoard(tt.getTurn().getBoard().getPlacement());

        PredefinedInOutPut piop = new PredefinedInOutPut();
        piop.setReceives(tt.getAdministrator().getResponses());

        ProxyOfTurnProxy potp = new ProxyOfTurnProxy(hexBoard, turn.getTile(), turn.getScore(), piop);

        RemoteTurnResults turnResults = takeYourTurn(potp, tt.getActions().getActions());
        List<Object> results = turnResults.getResults();
        if (results.size() == 0 ||
                (!(results.get(results.size() - 1) instanceof Bad) &&
                        potp.getRequiredPlacements() > 0)) {
            turnResults.getResults().add(new Bad("player did not finish placements"));
        }
        return turnResults;
    }

    private RemoteTurnResults takeYourTurn(final ProxyOfTurnProxy potp,
            final List<Object> actions) {
        List<Object> results = new ArrayList<Object>();
        try {
            for (Object obj : actions) {
                if (obj instanceof Placement) {
                    List<Tile> ret = potp.placeTile((Placement) obj);
                    if (ret.size() > 0) {
                        results.add(ret.get(0));
                    } else {
                        results.add(new False());
                    }
                } else if (obj instanceof ReRackPlease) {
                    potp.reRack();
                    results.add(new Rerack(potp.getAllTilesInPlayersHand()));
                } else if (obj instanceof Rerackable) {
                    potp.isReRackable();
                }
            }
        } catch (ContractAssertionError e) {
            results.add(new Bad(e.getMessage()));
        }
        RemoteTurnResults turnResults = new RemoteTurnResults(results);
        return turnResults;
    }

}
